package com.htjx.mall.admin.controllers.exception;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import com.htjx.mall.commons.api.Result;

public class GlobalExceptionHandlerResolver extends SimpleMappingExceptionResolver implements InitializingBean {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	private MappingJacksonHttpMessageConverter jsonHttpMessageConverter;

	@Override
	protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

		if (request.getRequestURI().startsWith("/common/")) {
			try {
				writeJson(response, ex, new Result(9, "系统未知异常"), MediaType.APPLICATION_JSON);
				return new ModelAndView();
			} catch (Exception e) {
			}
		}

		// Expose ModelAndView for chosen error view.
		String viewName = determineViewName(ex, request);
		if (viewName != null) {

			if (handler instanceof HandlerMethod) {
				try {
					HandlerMethod handlerMethod = (HandlerMethod) handler;
					ResponseBody responseBody = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), ResponseBody.class);
					if (responseBody != null) {
						HttpInputMessage inputMessage = new ServletServerHttpRequest(request);
						List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
						if (acceptedMediaTypes.isEmpty()) {
							acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
						}
						Result result = new Result(9, "系统异常");
						MediaType.sortByQualityValue(acceptedMediaTypes);
						if (jsonHttpMessageConverter != null) {
							for (MediaType acceptedMediaType : acceptedMediaTypes) {
								if (jsonHttpMessageConverter.canWrite(result.getClass(), acceptedMediaType)) {
									writeJson(response, ex, result, acceptedMediaType);
									return new ModelAndView();
								}
							}
						}
					}
				} catch (Exception e) {
				}
			}

			// Apply HTTP status code for error views, if specified.
			// Only apply it if we're processing a top-level request.
			Integer statusCode = determineStatusCode(request, viewName);
			if (statusCode != null) {
				applyStatusCodeIfPossible(request, response, statusCode);
			}
			return getModelAndView(viewName, ex, request);
		} else {
			return null;
		}
	}

	private void writeJson(HttpServletResponse response, Exception ex, Result result, MediaType mediaType) {
		try {
			response.setContentType("application/json;charset=utf-8");
			HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
			logger.error("系统未捕获的异常", ex);
			jsonHttpMessageConverter.write(result, mediaType, outputMessage);
		} catch (Exception e) {
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		jsonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
		List<MediaType> list = new ArrayList<MediaType>();
		list.add(MediaType.APPLICATION_JSON);
		jsonHttpMessageConverter.setSupportedMediaTypes(list);
	}
}
